﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using UIWindows.Models.Devices;
using XingLucifer.IBase.Enums;

namespace UIWindows.GlobalStatics
{
    [Attributes.Singleton]
    public class DeviceConfigStatic
    {
        public ObservableCollection<RJ6902RParametersModel> RJ6902R { get; set; }
        public ObservableCollection<ST5520ParametersModel> ST5520 { get; set; }
        public ObservableCollection<RJ6901AParametersModel> RJ6901A { get; set; }
        public ObservableCollection<DeviceClientModel> DeviceList { get; set; }

        public DeviceConfigStatic()
        {
#pragma warning disable CS8601 // 引用类型赋值可能为 null。
            DeviceList = !File.Exists(GlobalStatic.DevicePath)
                ? new ObservableCollection<DeviceClientModel>()
                : JsonSerializer.Deserialize<ObservableCollection<DeviceClientModel>>(File.ReadAllText(GlobalStatic.DevicePath, Encoding.UTF8));
            ST5520 = !File.Exists(GlobalStatic.ST5520Path) 
                ? new ObservableCollection<ST5520ParametersModel>()
                : JsonSerializer.Deserialize<ObservableCollection<ST5520ParametersModel>>(File.ReadAllText(GlobalStatic.ST5520Path, Encoding.UTF8));
            RJ6902R = !File.Exists(GlobalStatic.RJ6902RPath)
                ? new ObservableCollection<RJ6902RParametersModel>()
                : JsonSerializer.Deserialize<ObservableCollection<RJ6902RParametersModel>>(File.ReadAllText(GlobalStatic.RJ6902RPath, Encoding.UTF8));
#pragma warning restore CS8601 // 引用类型赋值可能为 null。

            RJ6901A = !File.Exists(GlobalStatic.RJ6901APath)
            ? new ObservableCollection<RJ6901AParametersModel>()
            : JsonSerializer.Deserialize<ObservableCollection<RJ6901AParametersModel>>(File.ReadAllText(GlobalStatic.RJ6901APath, Encoding.UTF8));


            var device_path = Path.GetDirectoryName(GlobalStatic.ST5520Path);
            if (!Directory.Exists(device_path))
            {
                Directory.CreateDirectory(device_path);
            }
        }

        public void Save() => File.WriteAllText(GlobalStatic.DevicePath, JsonSerializer.Serialize(DeviceList, GlobalStatic.Options), Encoding.UTF8);
        public void SaveST5520() => File.WriteAllText(GlobalStatic.ST5520Path, JsonSerializer.Serialize(ST5520, GlobalStatic.Options), Encoding.UTF8);
        public void SaveRJ6902R() => File.WriteAllText(GlobalStatic.RJ6902RPath, JsonSerializer.Serialize(RJ6902R, GlobalStatic.Options), Encoding.UTF8);

        public void SaveRJ6901A() => File.WriteAllText(GlobalStatic.RJ6901APath, JsonSerializer.Serialize(RJ6901A, GlobalStatic.Options), Encoding.UTF8);
        /// <summary>
        /// 添加单设备
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="ipcom"></param>
        /// <param name="port"></param>
        /// <param name="baudRate"></param>
        /// <param name="isSocket"></param>
        /// <param name="type"></param>
        public void Add(string ipcom, int port, int baudRate, bool isSocket, DeviceTypes type, TaskTypes taskTypes, string serviceName)
        {
            DeviceList.Add(new DeviceClientModel()
            {
                TaskType = taskTypes,
                ServiceName = serviceName,
                Index = 1,
                IPCOM = ipcom,
                Port = port,
                IsSocket = isSocket,
                DeviceType = type
            });
        }
        /// <summary>
        /// 生成IP地址
        /// </summary>
        /// <param name="startAddress">开始地址</param>
        /// <param name="startPort">开始端口</param>
        /// <param name="endAddress">结束地址</param>
        /// <param name="endPort">结束端口</param>
        public void AddDevices(string startAddress, string startPort, string endAddress, string endPort, bool isSocket, DeviceTypes type, TaskTypes taskTypes, string serviceName)
        {
            string[] str = new string[] { startAddress, startPort, endAddress, endPort };
            GenerateAddress(str, type, taskTypes,serviceName,
                GetAddressPortInt(str),
                DeviceList);
        }

        #region 计算IP地址差与生成
        private void GenerateAddress(string[] str, DeviceTypes deviceType, TaskTypes taskTypes, string serviceName, CalculateWeighingAddress calculate, ObservableCollection<DeviceClientModel> servers)
        {
            if (string.IsNullOrEmpty(str[0]) || string.IsNullOrEmpty(str[1]) || string.IsNullOrEmpty(str[2]) || string.IsNullOrEmpty(str[3])) return;
            int count = 0;
            if (calculate.IPLength == 0)
            {
                for (int i = 0; i <= calculate.PortLength; i++)
                {
                    count = i + 1;
                    int port = calculate.StartPort + i;
                    if (servers.Any(x => x.IsSocket && x.TaskType == taskTypes 
                    && x.ServiceName == serviceName 
                    && x.Index == count
                    && x.DeviceType == deviceType
                    && x.Port == port
                    && x.IPCOM == calculate.Address))
                    {
                        continue;
                    }
                    servers.Add(new DeviceClientModel()
                    {
                        TaskType = taskTypes,
                        ServiceName = serviceName,
                        IPCOM = calculate.Address,
                        Port = port,
                        DeviceType = deviceType,
                        IsSocket = true,
                        Index = count,
                    });
                }
                return;
            }
            for (int i = 0; i <= calculate.IPLength; i++)
            {
                count = i + 1;
                string ip = $"{calculate.StrArray[0]}.{calculate.StrArray[1]}.{calculate.StrArray[2]}.{calculate.StartIP + i}";
                if (servers.Any(x => x.IsSocket && x.TaskType == taskTypes
                && x.ServiceName == serviceName
                && x.Index == count
                && x.DeviceType == deviceType
                && x.Port == calculate.StartPort
                && x.IPCOM == ip))
                {
                    continue;
                }
                servers.Add(
                    new DeviceClientModel()
                    {
                        TaskType = taskTypes,
                        ServiceName = serviceName,
                        IPCOM = ip,
                        Port = calculate.StartPort,
                        DeviceType = deviceType,
                        IsSocket = true,
                        Index = count,
                    });
            }
        }

        private CalculateWeighingAddress GetAddressPortInt(string[] str)
        {
            string[] strArray = str[0].Split('.');
            var obj = new CalculateWeighingAddress()
            {
                Address = str[0],
                StrArray = strArray,
                StartIP = Convert.ToInt32(strArray[3]),
                StartPort = Convert.ToInt32(str[1]),
                EndIP = Convert.ToInt32(str[2].Split('.')[3]),
                EndPort = Convert.ToInt32(str[3])
            };
            obj.IPLength = obj.EndIP - obj.StartIP;
            obj.PortLength = obj.EndPort - obj.StartPort;
            return obj;
        }

        private class CalculateWeighingAddress
        {
            /// <summary>
            /// IP地址
            /// </summary>
            public string Address { get; set; }
            /// <summary>
            /// 开始地址最后一位
            /// </summary>
            public int StartIP { get; set; }
            /// <summary>
            /// 结束地址最后一位
            /// </summary>
            public int EndIP { get; set; }
            /// <summary>
            /// 开始端口号
            /// </summary>
            public int StartPort { get; set; }
            /// <summary>
            /// 结束端口号
            /// </summary>
            public int EndPort { get; set; }
            /// <summary>
            /// IP差
            /// </summary>
            public int IPLength { get; set; }
            /// <summary>
            /// 端口号差
            /// </summary>
            public int PortLength { get; set; }
            /// <summary>
            /// 分割IP地址后的数组
            /// </summary>
            public string[] StrArray { get; set; }
        }
        #endregion
    }
}
